#include <stdio.h>
#include "DES.h"
#include "crack.h"

int crack_K2()
{
  int four_bit_num;
  int bitnum,key_cnt=0;
  int i,j,k,index[8]={0,0,0,0,0,0,0,0};
  uchar keysI[65600][8],Rexp_Xor_K2_48[65600][6],temp1[8],temp2[8];
  uchar candidate_key[6];
  uchar combinations[8][4],dst[4];
  int noOfKeys=0;
  FILE *fp;

  /* Get output of Feistel cipher */
  uchar f_output[4];
  for(i=0; i<4; i++)
    f_output[i] = L1[0][i] ^ R2[0][i];

  /* Get output of S-Boxes */
  uchar s_output[4];  
  Permute( s_output, f_output, InversePBox, 4 );   

  /* Get output of Expansion boxes */
  uchar e_output[6];
  Permute(e_output, R1[0], DataExpansion, 6);

  fp=fopen("output.txt","w");
  for( i = 0; i < 8 ;i++ ) {
    /* Extract the 4-bit integer from the source.
     * This will be the lookup key within the InversSBox[i] array.
     */
    four_bit_num = 0;
    for( j = 0, bitnum = (i * 4); j < 4; j++, bitnum++ ) {
      four_bit_num <<= 1;
      four_bit_num  |= GETBIT(s_output, bitnum);
    }
    /* Index InverseSbox with 4-bit number to get 4 possible 6-bit
     * of the key */
    for(k=0;k<4;k++){
      combinations[i][k]=InversSbox[i][four_bit_num][k];
    }
  }
  
  //finding 2^16 combinations of R_XOR_K1
  while(index[0]<=3 && index[7]<=3){ 
    for(i=0; i<8; i++){
      keysI[noOfKeys][i]=combinations[i][index[i]];
    }
    noOfKeys++;
    if(noOfKeys == 65536){
      break;
    }
    for(j=7; j>=0; j--){
      index[j]=(index[j]+1);
      if(index[j]>3){
	index[j]=0;
      }
      else{
	break;
      }
    }
  }

  /* converting from 64 bit to 48 bit */
  int cnt;
  for(k=0;k<noOfKeys;k++){
    cnt=0;
    bitnum = 2;
    for(i=0;i<8;i++){
      temp1[i]=keysI[k][i];
    }
    
    for(j=0; j<8; j++ ){
      for( i = 0 ; i < 6; i++ ){
	if(GETBIT(temp1, bitnum)){
	  SETBIT(temp2,cnt);  
	}
        else{
          CLRBIT(temp2,cnt);
	}
 	bitnum++; 
        cnt++;
      }
      bitnum+=2;
    }
    for(i=0;i<6;i++){
      Rexp_Xor_K2_48[k][i]=temp2[i];
    }
    for(j=0;j<6;j++){
      candidate_key[j] = Rexp_Xor_K2_48[k][j]^e_output[j];
    }
    

    /* Check with all other blocks to see if candidate key is correct */
    int k;
    int correct = 1;
    for(k=0; k<BLOCKS; k++) {
      if( check_key(L1[k], R1[k], candidate_key, R2[k]) == 0 ) {
	correct = 0;
	break;
      }
    }
    if(correct) {
      for(i=0;i<6;i++){
	k2_match[key_cnt][i]=candidate_key[i];
      }
      key_cnt++;
      //printHex("K2", candidate_key, 6);
    }
  }
  return key_cnt;
}

